package com.superbit.web.listener;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.web.context.ConfigurableWebApplicationContext;

/**
 * 封装ApplicationContext对象， 使之只能获取beanname以Service结尾或使用@service标记的bean，可以保护其他bean不被外部调用
 */
public class ServiceBeanFactory {
	private static ApplicationContext applicationContext;
	private static List<String> serviceNames;
	
	
	public static void intApplicationContext(ApplicationContext ac){
		if(applicationContext!=null){
			throw new RuntimeException("ServiceBeanFactory已完成初始化");
		}
		applicationContext = ac;
	}
	
	/**获取所有使用@Service定义的SpringBean
	 * @return
	 */
	private static List<String>  getServiceNames(){
		if(serviceNames==null){
			String[]  names = applicationContext.getBeanNamesForAnnotation(Service.class);
			serviceNames = new ArrayList<String>(Arrays.asList(names));
		}
		return serviceNames;
	}
	
	/**通过BeanId获取ServiceBean
	 * @param beanId
	 * @return
	 */
	public static Object getBean(String beanId){
		Assert.notNull(beanId);
		if(beanId.endsWith("Service")){
			return applicationContext.getBean(beanId);
		}else{
			List<String> names = getServiceNames();
			if(names.contains(beanId)){
				return applicationContext.getBean(beanId);
			}else{
				throw new RuntimeException("不允许获取Service以外的Bean:"+beanId);
			}
		}
	}
	/**通过BeanId获取对应的ServiceBean
	 * @param beanId
	 * @param cls
	 * @return
	 */
	public static <T> T getBean(String beanId, Class<T> cls){
		Assert.notNull(beanId);
		if(beanId.endsWith("Service")){
			return applicationContext.getBean(beanId,cls);
		}else{
			List<String> names = getServiceNames();
			if(names.contains(beanId)){
				return applicationContext.getBean(beanId,cls);
			}else{
				throw new RuntimeException("不允许获取Service以外的Bean:"+beanId);
			}
		}
	}
	
	/**通过Class获取ServiceBean
	 * @param cls
	 * @return
	 */
	public static <T> T getBean(Class<T> cls){
		List<String> namesByType = getServiceNames();
		String[] namesByClass = applicationContext.getBeanNamesForType(cls);
		String beanname = null;
		for(String bnm : namesByClass){
			boolean bn = bnm.endsWith("Service")||namesByType.contains(bnm);
			if(bn){
				if(beanname==null){
					beanname = bnm;
				}else{
					throw new RuntimeException("存在多条符合条件的Bean:"+cls.getName());
				}
			}
		}
		if(beanname!=null){
			return applicationContext.getBean(beanname,cls);
		}else{
			throw new RuntimeException("未获取到符合条件的ServiceBean:"+cls.getName());
			
		}	

	}
	
	@SuppressWarnings("unchecked")
	public static <T> List<T>  getBeanList(Class<T> cls){
		List<Object> list = new ArrayList<Object>();
		List<String> namesByType = getServiceNames();
		String[] namesByClass = applicationContext.getBeanNamesForType(cls);
		for(String bnm : namesByClass){
			boolean bn = bnm.endsWith("Service")||namesByType.contains(bnm);
			if(bn){
				Object obj = applicationContext.getBean(bnm,cls);
				list.add(obj);
			}
		}
		return (List<T>)list;
	}

	public static void destoryApplilcationContext() {
		if(applicationContext!=null){
			if (applicationContext instanceof ConfigurableWebApplicationContext) {
				((ConfigurableWebApplicationContext) applicationContext).close();
			}
			applicationContext = null;
		}
	}

}
